﻿using MongoDB.Driver;
using Sustainalytics.BusinessResearchProductStates.Entities.ResearchState;
using Sustainalytics.ClientDW.Entities;
using Sustainalytics.MongoDB.Extensions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Sustainalytics.EsgRatings.BusinessLogic
{
    public class ResearchProductsDataReader
    {
        readonly IMongoCollection<ESG.Entities.IndicatorTemplate> templateCollection;
        readonly IMongoCollection<PeerGroup> peerGroupCollection;
        readonly IMongoCollection<CompanyType> companyTypeCollection;
        readonly IMongoCollection<TemplateType> templateTypeCollection;
        readonly IMongoCollection<CorporateData> corporateDataCollection;

        public ResearchProductsDataReader(IMongoCollection<ESG.Entities.IndicatorTemplate> templateCollection,
            IMongoCollection<PeerGroup> peerGroupCollection,
            IMongoCollection<TemplateType> templateTypeCollection,
            IMongoCollection<CompanyType> companyTypeCollection,
            IMongoCollection<CorporateData> corporateDataCollection

            )
        {
            this.corporateDataCollection = corporateDataCollection;
            this.templateTypeCollection = templateTypeCollection;
            this.companyTypeCollection = companyTypeCollection;
            this.peerGroupCollection = peerGroupCollection;
            this.templateCollection = templateCollection;
        }


        public static ResearchProductsDataReader GetInstance(string connectionString)
        {
            return new ResearchProductsDataReader(
                MongoFactory.GetCollectionFromDatabase<ESG.Entities.IndicatorTemplate>(connectionString),
                MongoFactory.GetCollectionFromDatabase<PeerGroup>(connectionString),
                MongoFactory.GetCollectionFromDatabase<TemplateType>(connectionString),
                MongoFactory.GetCollectionFromDatabase<CompanyType>(connectionString),
                MongoFactory.GetCollectionFromDatabase<CorporateData>(connectionString));
        }


        public async Task<HashSet<string>> ListIndicatorTemplatesNumbers()
        {
            return new HashSet<string>(await templateCollection
                                               .Find(FilterDefinition<ESG.Entities.IndicatorTemplate>.Empty)
                                               .Project(x => x.Number)
                                               .ToListAsync().ConfigureAwait(false));
        }

        public Task<List<string>> ListPeerGroupsNames()
        {
            return peerGroupCollection
                            .Find(FilterDefinition<PeerGroup>.Empty)
                            .Project(rpg => rpg.Name)
                            .ToListAsync();
        }

        public Task<List<string>> ListCompanyTypes()
        {
            return companyTypeCollection
                             .Find(FilterDefinition<CompanyType>.Empty)
                             .Project(ct => ct.Name)
                             .ToListAsync();
        }

        public Task<List<string>> ListTemplateTypes()
        {
            return templateTypeCollection
                            .Find(FilterDefinition<TemplateType>.Empty)
                            .Project(ct => ct.Name)
                            .ToListAsync();
        }

        public async Task<Dictionary<string, Guid>> ListCompaniesIds(bool? havingEsgResearch)
        {
            var filterDefinition = havingEsgResearch != null ? Builders<CorporateData>.Filter.Where(c => c.ComprehensiveEsgResearchState.ResearchState == ResearchState.ResearchAvailable) : FilterDefinition<CorporateData>.Empty;

            var result = await corporateDataCollection
                           .Find(filterDefinition)
                           .Project(cd => new { cd.CapitalIqId, cd.Id })
                           .ToListAsync();
            return result.ToDictionary(cd => cd.CapitalIqId.ToString(), cd => cd.Id, StringComparer.InvariantCultureIgnoreCase);
        }


        public Task<List<CorporateData>> ListCompaniesCorporateData()
        {
            var filterDefinition = Builders<CorporateData>.Filter.Where(c => c.ComprehensiveEsgResearchState.ResearchState == ResearchState.ResearchAvailable);
            return corporateDataCollection.Find(filterDefinition) .ToListAsync();
        }


        public Task<List<CorporateData>> ListCompaniesCorporateData(IEnumerable<Guid> companyIds)
        {
            return corporateDataCollection
                           .Find(c => companyIds.Contains(c.Id))
                           .ToListAsync();
        }


        public async Task<Dictionary<string, string>> ListIndicatorTemplatesNames(List<string> indicatorsNumbers=null)
        {
            var filterDefinition = indicatorsNumbers != null ?
                Builders<ESG.Entities.IndicatorTemplate>.Filter.Where(x => indicatorsNumbers.Contains(x.Number)) :
                FilterDefinition<ESG.Entities.IndicatorTemplate>.Empty;
            var result = await templateCollection
                            .Find(filterDefinition)
                            .Project(it => new { it.Number, it.Name })
                            .ToListAsync().ConfigureAwait(false);
            return result.ToDictionary(it => it.Number, it => it.Name);
        }
    }
}